<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
<html>
<head>
<script src="../../resources/js-test.js"></script>
</head>
<body>
<p id="description"></p>
<div id="console"></div>
<script>
description("This test checks the form attribute of the form-associated elements.");

var container = document.createElement('div');
document.body.appendChild(container);

debug('- Checks the existence of the form attribute for each form-associated elements.');
container.innerHTML = '<form id=owner></form>' +
    '<button name=victim form=owner />' +
    '<fieldset name=victim form=owner />' +
    '<input name=victim form=owner />' +
    '<label name=victim form=owner></label>' +
    '<object name=victim form=owner></object>' +
    '<output name=victim form=owner />' +
    '<select name=victim form=owner />' +
    '<textarea name=victim form=owner />';

var owner = document.getElementById('owner');
shouldBe('document.getElementsByTagName("button")[0].form', 'owner');
shouldBe('document.getElementsByTagName("fieldset")[0].form', 'owner');
shouldBe('document.getElementsByTagName("input")[0].form', 'owner');
shouldBeNull('document.getElementsByTagName("label")[0].form');
shouldBe('document.getElementsByTagName("object")[0].form', 'owner');
shouldBe('document.getElementsByTagName("output")[0].form', 'owner');
shouldBe('document.getElementsByTagName("select")[0].form', 'owner');
shouldBe('document.getElementsByTagName("textarea")[0].form', 'owner');

debug('');
debug('- Ensures that the form attribute points the form owner even if the element is within another form element.');
container.innerHTML = '<form id=owner></form>' +
    '<form id=shouldNotBeOwner>' +
    '    <input id=inputElement name=victim form=owner />' +
    '    <label id=labelElement name=victim for=inputElement />' +
    '</form>';
owner = document.getElementById('owner');
var inputElement = document.getElementById('inputElement');
var labelElement = document.getElementById('labelElement');
shouldBe('inputElement.form', 'owner');
shouldBe('labelElement.form', 'owner');


debug('');
debug('- Ensures that the form attribute of all form-associated element with or witout form attribute points the form owner.');
container.innerHTML = '<form id=owner>' +
    '    <input id=inputElement1 name=victim />' +
    '    <input id=inputElement2 name=victim form=owner />' +
    '    <input id=inputElement3 name=victim />' +
    '    <label id=labelElement1 name=victim />' +
    '    <label id=labelElement2 name=victim form=owner />' +
    '    <label id=labelElement3 name=victim />' +
    '</form>';
owner = document.getElementById('owner');
var inputElement1 = document.getElementById('inputElement1');
var inputElement2 = document.getElementById('inputElement2');
var inputElement3 = document.getElementById('inputElement3');
var labelElement1 = document.getElementById('labelElement1');
var labelElement2 = document.getElementById('labelElement2');
var labelElement3 = document.getElementById('labelElement3');
shouldBe('inputElement1.form', 'owner');
shouldBe('inputElement2.form', 'owner');
shouldBe('inputElement3.form', 'owner');
shouldBeNull('labelElement1.form');
shouldBeNull('labelElement2.form');
shouldBeNull('labelElement3.form');

debug('');
debug('- Ensures that the form attribute points the form owner even if the form element is nested another form element.');
debug('NOTE: It seems that nesting form elements is not allowed so we ensure each form-associated elements associate with the outmost form element.');
container.innerHTML = '<form id=owner>' +
    '    <form>' +
    '        <input id=inputElement1 name=victim form=owner />' +
    '        <input id=inputElement2 name=victim />' +
    '        <input id=inputElement3 name=victim form=owner />' +
    '        <label id=labelElement1 name=victim form=owner />' +
    '        <label id=labelElement2 name=victim />' +
    '        <label id=labelElement3 name=victim form=owner />' +
    '    </form>' +
    '</form>';
owner = document.getElementById('owner');
inputElement1 = document.getElementById('inputElement1');
inputElement2 = document.getElementById('inputElement2');
inputElement3 = document.getElementById('inputElement3');
labelElement1 = document.getElementById('labelElement1');
labelElement2 = document.getElementById('labelElement2');
labelElement3 = document.getElementById('labelElement3');
shouldBe('inputElement1.form', 'owner');
shouldBe('inputElement2.form', 'owner');
shouldBe('inputElement3.form', 'owner');
shouldBeNull('labelElement1.form');
shouldBeNull('labelElement2.form');
shouldBeNull('labelElement3.form');

debug('');
debug('- Ensures whether the form owner is set correctly when the value of form attribute of a form-associated element changed.');
container.innerHTML = '<form id=form1></form>' +
    '<form id=form2></form>' +
    '<input id=inputElement name=victim form=form1 />' +
    '<object id=objectElement name=victim form=form1></object>';
var form1 = document.getElementById('form1');
var form2 = document.getElementById('form2');
inputElement = document.getElementById('inputElement');
shouldBe('inputElement.form', 'form1');
inputElement.attributes['form'].value = 'form2';
shouldBe('inputElement.form', 'form2');

// HTMLObjectElement has its own implementation of formAttr processing and so needs its own test.
objectElement = document.getElementById('objectElement');
shouldBe('objectElement.form', 'form1');
objectElement.attributes['form'].value = 'form2';
shouldBe('objectElement.form', 'form2');

debug('');
debug('- Ensures whether the form owner is set correctly when the value of form attribute is added/removed.');
container.innerHTML = '<form id=owner name=firstOwner></form>' +
    '<input id=inputElement name=victim />' +
    '<object id=objectElement name=victim></object>';
owner = document.getElementById('owner');
inputElement = document.getElementById('inputElement');
shouldBe('inputElement.form', 'null');
var formAttribute = document.createAttribute('form');
inputElement.setAttribute('form', 'owner');
shouldBe('inputElement.form', 'owner');
inputElement.removeAttribute('form');
shouldBe('inputElement.form', 'null');

// HTMLObjectElement has its own implementation of formAttr processing and so needs its own test.
objectElement = document.getElementById('objectElement');
shouldBe('objectElement.form', 'null');
objectElement.setAttribute('form', 'owner');
shouldBe('objectElement.form', 'owner');
objectElement.removeAttribute('form');
shouldBe('objectElement.form', 'null');

debug('');
debug('- Ensures whether the form owner is set correctly when the form owner is added/removed.');
container.innerHTML = '<form id=owner name=firstOwner></form>' +
    '<form id=owner name=secondOwner></form>' +
    '<input id=inputElement name=victim form=owner />';
owner = document.getElementById('owner');
shouldBeEqualToString('owner.name', 'firstOwner');
inputElement = document.getElementById('inputElement');
container.removeChild(owner);
owner = document.getElementById('owner');
shouldBeEqualToString('owner.name', 'secondOwner');
shouldBe('inputElement.form', 'owner');
container.removeChild(owner);
shouldBe('inputElement.form', 'null');
container.appendChild(owner);
shouldBe('inputElement.form', 'owner');

debug('');
debug('- Check if a form and a control are disassociated when they are removed from the document together.');
container.innerHTML = '<div><input form=owner><form id=owner></form></div>';
owner = document.getElementById('owner');
shouldBe('owner.elements.length', '1');
container.firstChild.remove();
shouldBe('owner.elements.length', '0');

debug('');
debug('- Checks if option.form is only set if it has a &lt;select&gt; parent.');
container.innerHTML = '<form id=firstOwner><option id=firstOption></option></form>' +
    '<form id=secondOwner><optgroup><option id=secondOption></option></optgroup></form>' +
    '<form id=thirdOwner><select><optgroup><option id=thirdOption></option></optgroup></select></form>';
var option1 = document.getElementById('firstOption');
shouldBe('option1.form', 'null');
var option2 = document.getElementById('secondOption');
shouldBe('option2.form', 'null');
owner = document.getElementById('thirdOwner');
var option3 = document.getElementById('thirdOption');
shouldBe('option3.form', 'owner');

debug('');
debug('- Checks if updating form[id] correctly works');
container.innerHTML = '<form id="a"></form><form id="a"><select form="a"></select></form>';
form1 = document.querySelectorAll('form')[0];
form2 = document.querySelectorAll('form')[1];
var control = document.querySelector('select');
shouldBe('control.form', 'form1');
shouldBe('form1.setAttribute("id", "b"); control.form', 'form2');

container.remove();
</script>
</body>
</html>
